package com.thread.exe;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionBoundedBuffer<T> {
	private static final int BUFFER_SIZE = 10;
	protected final Lock lock = new ReentrantLock();
	private final Condition notFull = lock.newCondition();
	private final Condition notEmpty = lock.newCondition();
	
	@SuppressWarnings("unchecked")
	private final T[] items = (T[]) new Object[BUFFER_SIZE];
	private int tail, head, count;
	
	public void put(T x) {
		try {
			lock.lock();
			while(count == items.length) {
				notFull.await();
			}
			items[tail++] = x;
			++count;
			notEmpty.signal();
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		} finally {
			lock.unlock();
		}
	}
	
	public T take() throws InterruptedException {
		try {
			lock.lock();
			while(count == 0) {
				notEmpty.await();
			}
			T x = items[head++];
			--count;
			notFull.signal();
			return x;
		} finally {
			lock.unlock();
		}
	}
}
